/*
	Personal Bug Tracker (www.personalbugtracker.com)
	Copyright (C) 2014 Sergey Nechaev <serg.nechaev@gmail.com>

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/
package com.personalbugtracker.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

@Entity
@Table(name = "ISSUE")
public class Issue implements Serializable {

	public static enum Type {
		BUG, FEATURE, REQUIREMENT, DEV_TASK
	}

	public static enum Severity {
		CRITICAL, MAJOR, MODERATE, MINOR, COSMETIC
	}

	@Id
	@Column(name = "ID")
	@GeneratedValue(strategy = GenerationType.AUTO)
	private int id;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "PROJECT_ID")
	private Project project;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "COMPONENT_ID")
	private Component component;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "FOUND_VERSION_ID")
	private Version foundVersion;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "PARENT_ID")
	private Issue parent;

	@Column(name = "TYPE")
	@Enumerated(EnumType.STRING)
	private Type type;

	@Column(name = "SEVERITY")
	@Enumerated(EnumType.STRING)
	private Severity severity;

	@Column(name = "SUMMARY", length = 255)
	private String summary;

	@Column(name = "DESCRIPTION", length = 4096)
	private String description;

	@Column(name = "ENVIRONMENT", length = 255)
	private String environment;

	@Column(name = "REPORTER", length = 255, nullable = true)
	private String reporter;

	@Column(name = "ASSIGNEE", length = 255, nullable = true)
	private String assignee;

	@Column(name = "CREATE_DATE")
	private Date createDate;

	@Column(name = "UPDATE_DATE")
	private Date updateDate;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "FIX_VERSION_ID")
	private Version fixScheduledVersion;

	@Column(name = "FIX_BUILD", length = 255)
	private String fixBuild;

	@Column(name = "FIX_DETAILS", length = 4096)
	private String fixDetails;

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "issue")
	private Set<FileAttachment> fileAttachments;

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "issue")
	private Set<ScreenshotAttachment> screenshotAttachments;

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "issue")
	private Set<Comment> comments;

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "source")
	private Set<Link> linksFrom;

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "dest")
	private Set<Link> linksTo;

	public String getReporter() {
		return reporter;
	}

	public void setReporter(String reporter) {
		this.reporter = reporter;
	}

	public String getAssignee() {
		return assignee;
	}

	public void setAssignee(String assignee) {
		this.assignee = assignee;
	}

	public Project getProject() {
		return project;
	}

	public void setProject(Project project) {
		this.project = project;
	}

	public Component getComponent() {
		return component;
	}

	public void setComponent(Component component) {
		this.component = component;
	}

	public Version getFoundVersion() {
		return foundVersion;
	}

	public void setFoundVersion(Version foundVersion) {
		this.foundVersion = foundVersion;
	}

	public Issue getParent() {
		return parent;
	}

	public void setParent(Issue parent) {
		this.parent = parent;
	}

	public Type getType() {
		return type;
	}

	public void setType(Type type) {
		this.type = type;
	}

	public Severity getSeverity() {
		return severity;
	}

	public void setSeverity(Severity severity) {
		this.severity = severity;
	}

	public String getSummary() {
		return summary;
	}

	public void setSummary(String summary) {
		this.summary = summary;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getEnvironment() {
		return environment;
	}

	public void setEnvironment(String environment) {
		this.environment = environment;
	}

	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	public Date getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(Date updateDate) {
		this.updateDate = updateDate;
	}

	public Version getFixScheduledVersion() {
		return fixScheduledVersion;
	}

	public void setFixScheduledVersion(Version fixScheduledVersion) {
		this.fixScheduledVersion = fixScheduledVersion;
	}

	public String getFixBuild() {
		return fixBuild;
	}

	public void setFixBuild(String fixBuild) {
		this.fixBuild = fixBuild;
	}

	public String getFixDetails() {
		return fixDetails;
	}

	public void setFixDetails(String fixDetails) {
		this.fixDetails = fixDetails;
	}

	public Set<FileAttachment> getFileAttachments() {
		return fileAttachments;
	}

	public void setFileAttachments(Set<FileAttachment> fileAttachments) {
		this.fileAttachments = fileAttachments;
	}

	public Set<ScreenshotAttachment> getScreenshotAttachments() {
		return screenshotAttachments;
	}

	public void setScreenshotAttachments(Set<ScreenshotAttachment> screenshotAttachments) {
		this.screenshotAttachments = screenshotAttachments;
	}

	public Set<Comment> getComments() {
		return comments;
	}

	public void setComments(Set<Comment> comments) {
		this.comments = comments;
	}

	public Set<Link> getLinksFrom() {
		return linksFrom;
	}

	public void setLinksFrom(Set<Link> linksFrom) {
		this.linksFrom = linksFrom;
	}

	public Set<Link> getLinksTo() {
		return linksTo;
	}

	public void setLinksTo(Set<Link> linksTo) {
		this.linksTo = linksTo;
	}

	public int getId() {
		return id;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + id;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Issue other = (Issue) obj;
		if (id != other.id)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
	}

}
